
#pragma once

#ifdef DEBUG
    #define dASSERT_CHECK_RANGE_INCREMENT \
        const bool ERROR_OUT_OF_RANGE_INCREMENT = mCur >= mBeg+1 || mCur<mBeg; \
        assert(!ERROR_OUT_OF_RANGE_INCREMENT);

    #define dASSERT_CHECK_RANGE_DECREMENT \
        const bool ERROR_OUT_OF_RANGE_DECREMENT = mCur <= mBeg || mCur > mBeg+1; \
        assert(!ERROR_OUT_OF_RANGE_DECREMENT);
#else
    #define dASSERT_CHECK_RANGE_INCREMENT ;
    #define dASSERT_CHECK_RANGE_DECREMENT ;
#endif 

#define dCHECK_DIRECTLY \
    enum { eIS_NORMAL  = ::std::is_same<DIRECTLY,DIRECT_NORMAL>::value  };\
    enum { eIS_REVERSE = ::std::is_same<DIRECTLY,DIRECT_REVERSE>::value };\
    enum { eIS_VALID = eIS_NORMAL || eIS_REVERSE };\
    static_assert(eIS_VALID, "DIRECTLY most be DIRECT_NORMAL or DIRECT_REVERSE")


namespace tools{
    namespace variant_detail{
    
        struct DIRECT_REVERSE;
        struct DIRECT_NORMAL;
        struct CONST_ITERATOR;

        template<class T, class DIRECTLY=DIRECT_NORMAL> struct PrimitiveIterator
        {
            dCHECK_DIRECTLY;

            #define My PrimitiveIterator

            typedef T value_type;

            My(const My& obj): mBeg(obj.mBeg), mCur(obj.mCur){}
            My& operator=(const My& rhs){ mBeg = rhs.mBeg; mCur = rhs.mCur; return *this; }


            My(T& obj):  mBeg(&obj), mCur(&obj){}

            // преффиксная форма ++it
            My& operator++()             { dASSERT_CHECK_RANGE_INCREMENT; ++mCur; return *this; }
            // преффиксная форма --it
            My& operator--()             { dASSERT_CHECK_RANGE_DECREMENT; --mCur; return *this; }
            
            const T* operator->()const { return mCur; }


            T* operator->() { return mCur; }

            bool operator==(const My& rhs)const{ return mCur == rhs.mCur; }

            #undef My
        protected:
            const T* mBeg;
            T* mCur;
        };

//--------------------------------------------------------------------------------------

    }//namespace variant_detail
}//namespace tools


